#!/usr/bin/env python3

# Copyright (c) 2005-2014 Fpemud <fpemud@sina.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

import os
import sys
from config import Config


class Main:

    @classmethod
    def usage(cls):
        clist = cls._getCategories()

        print('Usage: windown [options...] <product> [product-options...]')
        print('')
        print('Available options:')
        print('  --verbose-level: verbose level (0-2), default is 2.')
        print('  --directory: download into the specified directory instead of current directory.')
        print('')
        for c in clist:
            print('For product category "%s":' % (c.get_category_name()))
            print('  available products:')
            if len(c.get_product_id_list()) > 0:
                maxLen = max([len(x) for x in c.get_product_id_list()])
                for id in c.get_product_id_list():
                    print('      %s: %s%s' % (id, " " * (maxLen - len(id)), c.get_product_description(id)))
            else:
                print('    None')
            print('  supported product options:')
            for line in c.get_category_cmdline_option_description().split("\n"):
                if line != "":
                    print('    ' + line)
            print('')

    @staticmethod
    def die(msg):
        print(msg, file=sys.stderr)
        sys.exit(1)

    @classmethod
    def main(cls):
        clist = cls._getCategories()

        c = 1
        destDir = None
        categoryObj = None

        if len(sys.argv) <= c:
            cls.usage()
            sys.exit(1)

        if sys.argv[c] == "--help":
            cls.usage()
            sys.exit(0)

        while len(sys.argv) > c:
            if sys.argv[c] == "--verbose-level" or sys.argv[c].startswith("--verbose-level="):
                if sys.argv[c] == "--verbose-level":
                    c += 1
                    if len(sys.argv) <= c:
                        cls.die("Missing verbose level.")
                    Config.verboseLevel = sys.argv[c]
                    c += 1
                elif sys.argv[c].startswith("--verbose-level="):
                    Config.verboseLevel = sys.argv[c][len("--verbose-level="):]
                    c += 1
                else:
                    assert False

                try:
                    Config.verboseLevel = int(Config.verboseLevel)
                except ValueError:
                    cls.die("Verbose level is invalid.")

                if not (0 <= Config.verboseLevel <= 2):
                    cls.die("Verbose level must be in range 0-2.")

                continue

            if sys.argv[c] == "--directory":
                c += 1
                if len(sys.argv) <= c:
                    cls.die("Missing target directory.")
                destDir = sys.argv[c]
                c += 1
                continue

            productId = sys.argv[c]
            categoryObj = cls._getCategoryByProductId(clist, productId)
            if categoryObj is None:
                cls.die("Invalid product.")
            c += 1

            c = categoryObj.set_product_and_parse_cmdline(productId, sys.argv, c, cls.die)
            if c < len(sys.argv):
                cls.die("Redundant argument(s) found.")

        if categoryObj is None:
            cls.die("No product specified."),

        if destDir is None:
            destDir = "."
        if not os.path.isdir(destDir):
            cls.die("Target directory \"%s\" does not exists or is invalid." % (destDir))
        if len(os.listdir(destDir)) > 0:
            print("WARNNING: Target directory \"%s\" is not empty, files may be overwritten.")

        if not os.path.isdir(Config.cacheDir):
            cls.die("Cache directory %s does not exist" % (Config.cacheDir))

        cacheDir = os.path.join(Config.cacheDir, productId)
        os.makedirs(cacheDir, exist_ok=True)
        categoryObj.download(cacheDir, destDir)

    @staticmethod
    def _getCategories():
        # we use a name list to apply category order
        nameList = ["win98", "winxp", "win7", "win10", "win11", "office"]

        ret = []
        for n in nameList:
            try:
                exec("from cat_%s import Category" % (n))
                ret.append(eval("Category()"))
            except ModuleNotFoundError:
                assert False
        return ret

    @staticmethod
    def _getCategoryByProductId(categoryList, productId):
        for c in categoryList:
            if productId in c.get_product_id_list():
                return c
        return None
